package com.qf.spring2202.proxypattern.utils;

import com.qf.spring2202.proxypattern.service.UserService;
import com.qf.spring2202.proxypattern.service.impl.UserServicImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理工具类
 */
public class MyProxyFactory {

    /**
     *
     * @param target 原始对象
     * @return 动态代理对象
     */
    public static Object getProxy(Object target){


        final InvocationHandler handler = new InvocationHandler() {

            /**
             *
             * @param proxy 动态对象本身
             * @param method 在 动态代理对象上调用了哪个方法
             * @param args 在动态代理对象上调用方法时，所传递的参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                // 判断一下，，method是不是属于 Object 类型 ，如果是Object中定义的方法，则不做时间统计
                if (method.getDeclaringClass().equals(Object.class)) {
                    //2. 让原始对象的目标方法执行
                    final Object result = method.invoke(target, args);
                    return result;
                }

                //1. 添加辅助功能
                final long start = System.currentTimeMillis();

                //2. 让原始对象的目标方法执行
                final Object result = method.invoke(target, args);

                final long end = System.currentTimeMillis();
                System.out.println("time usesd = "+(end-start));

                return result;
            }
        };

        // JDK 提供的创建动态代理对象的 方法
        /**
         * 参数1：classLoader，用于加载动态生成的class文件
         * 参数2：规定了动态生成的对象的类型，即该对象实现了哪些接口
         * 参数3：添加的辅助功能写在该对象中
         */
        final Object o = Proxy.newProxyInstance(MyProxyFactory.class.getClassLoader(),
                target.getClass().getInterfaces(), handler);

        // 需要理解，动态生成的对象o,里面的方法是什么样的？
        return o;
    }


    public static void main(String[] args) {
        //1 . 创建原始对象
        final UserService userServic = new UserServicImpl();
        //2 . 调用动态代理工具类，为原始对象赋能
        final UserService proxy = (UserService) MyProxyFactory.getProxy(userServic);
        //3 . 调用代理对象
        proxy.helloUser();

        proxy.getUserByName("luffy");
    }
}
